pub mod admin;
pub mod blog;

use crate::middleware::global;
use admin::router_admin;
use hypers::prelude::{Request, Responder, Response, Router, StaticDir};
use serde::Serialize;

pub fn render(app_state: &AppState, name: &str) -> Response {
    let mut res = Response::default();
    let body = match app_state.view.render(name, &app_state.ctx) {
        Ok(v) => v,
        Err(e) => {
            res.status(500).text(e.to_string());
            return res;
        }
    };
    res.status(200).html(body);
    res
}

// 返回失败页面
pub fn error_admin_html(app_state: &AppState, message: &str, url: &str) -> Response {
    let mut new_url = url;
    if new_url == "back" {
        new_url = "javascript:history.back(-1);";
    }
    let mut ctx = tera::Context::new();
    ctx.insert("message", &message.to_string());
    ctx.insert("url", &new_url.to_string());
    render(app_state, "admin/error/index.html")
}

pub fn request_base_url(req: &Request) -> String {
    let url = req.uri().path();
    let ss = url.split('/').collect::<Vec<&str>>();
    format!("{}//{}/", ss[0], ss[2])
}

#[derive(Clone)]
pub struct AppState {
    pub view: tera::Tera,
    pub ctx: tera::Context,
}

/// 状态枚举
#[derive(Serialize)]
pub enum Status {
    SUCCESS,
    FAIL,
}

/// 输出数据
#[derive(Serialize)]
pub struct ApiResult<T> {
    pub status: Status,
    pub code: i64,
    pub message: String,
    pub data: Option<T>,
}

impl<T: Serialize> Responder for ApiResult<T> {
    fn response(self, mut builder: Response) -> Response {
        builder.status(200).json(&self);
        builder
    }
}

// 返回失败 json
pub fn error_response_json(message: &str) -> Response {
    let res_body: ApiResult<String> = ApiResult {
        status: Status::FAIL,
        code: 1,
        message: message.to_owned(),
        data: Some("".to_owned()),
    };
    let mut res = Response::default();
    res.status(200).json(&res_body);
    res
}

// 返回成功 json
pub fn success_response_json<T: Serialize>(message: &str, data: T) -> Response {
    let res_body: ApiResult<T> = ApiResult {
        status: Status::SUCCESS,
        code: 0,
        message: message.to_string(),
        data: Some(data),
    };
    let mut res = Response::default();
    res.status(200).json(&res_body);
    res
}

pub fn router() -> Router {
    let mut root = Router::default();
    root.hook_single(global, "/{*p}");
    root.get("/{*p}", StaticDir::new("assert/static"));
    router_admin(&mut root);
    root.swagger("swagger-ui", None);
    root
}
